home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / winlib.lzh / WINLIB / DRAGDROP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-23  |  7.6 KB  |  336 lines

  1. /********************************************************************
  2.  *                                                                    *
  3.  *    Drag and drop protocol routines                                    *
  4.  *    for MiNT and MultiTOS desktops only                                *
  5.  *                                                                    *
  6.  *    BUGS/CAVEATS:                                                    *
  7.  *    This code is not re-entrant (it uses a static variable for the    *
  8.  *    pipe name and for saving the SIGPIPE signal handler)            *
  9.  *                                                                    *
  10.  *    While doing the drag and drop, the SIGPIPE signal (write on an    *
  11.  *    empty pipe) is ignored                                            *
  12.  *                                                                    *
  13.  *    Copyright (C) 1992, Atari Corporation                            *
  14.  *                                                                    *
  15.  *    Since these are Atari's routines, these will not be modified.    *
  16.  *    WinLIB PRO's Drag-and-drop protocol will be used in DDWINLIB.C    *
  17.  *                                                                    *
  18.  ********************************************************************/
  19.  
  20. #include <tos.h>
  21. #include <string.h>
  22. #include "winlib.h"
  23.  
  24. #ifndef Word
  25. #define Word short
  26. #define Long long
  27. #endif
  28.  
  29. #ifndef EACCDN
  30. #define EACCDN -36
  31. #endif
  32.  
  33. #ifndef SIGPIPE
  34. #define SIGPIPE 13
  35. #endif
  36.  
  37. #ifndef SIG_IGN
  38. #define SIG_IGN 1L
  39. #endif
  40.  
  41. #ifndef WF_OWNER
  42. #define WF_OWNER 20
  43. #endif
  44.  
  45. #ifndef FA_HIDDEN
  46. #define FA_HIDDEN 0x2
  47. #endif
  48.  
  49. extern int gl_apid;
  50.  
  51. static char pipename[] = "U:\\PIPE\\DRAGDROP.AA";
  52. static long oldpipesig;
  53.  
  54. #ifdef DEBUGGING
  55. #define debug_alert(x, y) form_alert(x, y)
  56. #else
  57. #define debug_alert(x, y)
  58. #endif
  59.  
  60. /* Code for originator */
  61.  
  62. /*
  63.  *    Create a pipe for doing the drag-and-drop, and send an AES
  64.  *    message to the recipient application telling it about the drag-
  65.  *    and-drop operation.
  66.  *
  67.  *    Input Parameters:
  68.  *    apid:        AES id of the window owner
  69.  *    winid:        target window (0 for background)
  70.  *    msx, msy:    mouse X and Y position (or -1, -1 if a fake drag-and-
  71.  *                drop)
  72.  *     kstate:        shift key state at time of event
  73.  *
  74.  *    Output Parameters:
  75.  *     exts:    A 32 byte buffer into which the receipient's 8 favorite
  76.  *            extensions will be copied.
  77.  *
  78.  *    Returns:
  79.  *    A positive file descriptor (of the opened drag-and-drop pipe) on
  80.  *    success.
  81.  *    -1 if the receipient doesn't respond or returns DD_NAK
  82.  *    -2 if appl_write fails
  83.  */
  84.  
  85. GLOBAL int ddcreate(int apid, int winid, int msx, int msy, int kstate, char exts[])
  86. {
  87.     int fd, i;
  88.     int msg[8];
  89.     long fd_mask;
  90.     char c;
  91.  
  92.     pipename[17] = pipename[18] = 'A';
  93.     fd = -1;
  94.     do {
  95.         pipename[18]++;
  96.         if (pipename[18] > 'Z') {
  97.             pipename[17]++;
  98.             if (pipename[17] > 'Z')
  99.                 break;
  100.         }
  101. /* FA_HIDDEN means "get EOF if nobody has pipe open for reading" */
  102.         fd = (int)(Fcreate(pipename, FA_HIDDEN));
  103.     } while (fd == EACCDN);
  104.  
  105.     if (fd < 0) {
  106.         debug_alert(1, "[1][Fcreate error][OK]");
  107.         return fd;
  108.     }
  109.  
  110. /* Construct and send the AES message */
  111.     msg[0] = AP_DRAGDROP;
  112.     msg[1] = gl_apid;
  113.     msg[2] = 0;
  114.     msg[3] = winid;
  115.     msg[4] = msx;
  116.     msg[5] = msy;
  117.     msg[6] = kstate;
  118.     msg[7] = (pipename[17] << 8) | pipename[18];
  119.     i = appl_write(apid, 16, msg);
  120.     if (i == 0) {
  121.         debug_alert(1, "[1][appl_write error][OK]");
  122.         Fclose(fd);
  123.         return -2;
  124.     }
  125.  
  126. /* Now wait for a response */
  127.     fd_mask = 1L << fd;
  128.     i = Fselect(DD_TIMEOUT, &fd_mask, 0L, 0L);
  129.     if (!i || !fd_mask) {    /* Timeout happened */
  130.         debug_alert(1, "[1][ddcreate: Fselect timeout][OK]");
  131. abort_dd:
  132.         Fclose(fd);
  133.         return -1;
  134.     }
  135.  
  136. /* Read the 1 byte response */
  137.     i = (int)(Fread(fd, 1L, &c));
  138.     if (i != 1 || c != DD_OK) {
  139.         if (i != 1)
  140.             debug_alert(1, "[1][ddcreate: read error][OK]");
  141.         else
  142.             debug_alert(1, "[1][ddcreate: DD_NAK][OK]");
  143.         goto abort_dd;
  144.     }
  145.  
  146. /* Now read the "preferred extensions" */
  147.     i = (int)(Fread(fd, DD_EXTSIZE, exts));
  148.     if (i != DD_EXTSIZE) {
  149.         debug_alert(1, "[1][Error reading extensions][OK]");
  150.         goto abort_dd;
  151.     }
  152.  
  153.     oldpipesig = Psignal(SIGPIPE, SIG_IGN);
  154.     return fd;
  155. }
  156.  
  157.  
  158. /*
  159.  *    See if the recipient is willing to accept a certain type of data
  160.  *    (as indicated by "ext")
  161.  *
  162.  *    Input parameters:
  163.  *    fd        file descriptor returned from ddcreate()
  164.  *    ext        pointer to the 4 byte file type
  165.  *    name    pointer to the name of the data
  166.  *    size    number of bytes of data that will be sent
  167.  *
  168.  *    Output parameters: none
  169.  *
  170.  *    Returns:
  171.  *    DD_OK    if the receiver will accept the data
  172.  *    DD_EXT    if the receiver doesn't like the data type
  173.  *    DD_LEN    if the receiver doesn't like the data size
  174.  *    DD_NAK    if the receiver aborts
  175.  */
  176.  
  177. GLOBAL int ddstry(int fd, char *ext, char *name, long size)
  178. {
  179.     Word hdrlen, i;
  180.     char c;
  181.  
  182. /* 4 bytes for extension, 4 bytes for size, 1 byte for trailing 0 */
  183.     hdrlen = 9 + strlen(name);
  184.     i = Fwrite(fd, 2L, &hdrlen);
  185.  
  186. /* Now send the header */
  187.     if (i != 2) return DD_NAK;
  188.     i = Fwrite(fd, 4L, ext);
  189.     i += Fwrite(fd, 4L, &size);
  190.     i += Fwrite(fd, (long)strlen(name)+1, name);
  191.     if (i != hdrlen) return DD_NAK;
  192.  
  193. /* Wait for a reply */
  194.     i = Fread(fd, 1L, &c);
  195.     if (i != 1) return DD_NAK;
  196.     return c;
  197. }
  198.  
  199. /*
  200.  * Close a drag-and-drop operation
  201.  */
  202. GLOBAL void ddclose(int fd)
  203. {
  204.     (void)Psignal(SIGPIPE, oldpipesig);
  205.     (void)Fclose(fd);
  206. }
  207.  
  208. /*
  209.  *    open a drag-and-drop pipe
  210.  *
  211.  *    Input Parameters:
  212.  *    ddnam:        the pipe's name (from the last word of
  213.  *                the AES message)
  214.  *    preferext:    a list of DD_NUMEXTS 4 byte extensions we understand
  215.  *                these should be listed in order of preference
  216.  *                if we like fewer than DD_NUMEXTS extensions, the
  217.  *                list should be padded with 0s
  218.  *
  219.  *    Output Parameters: none
  220.  *
  221.  *    Returns:
  222.  *    A (positive) file handle for the drag & drop pipe, on success
  223.  *    -1 if the drag & drop is aborted
  224.  *    A negative error number if an error occurs while opening the
  225.  *    pipe.
  226.  */
  227. GLOBAL int ddopen(int ddnam, char *preferext)
  228. {
  229.     int fd;
  230.     char outbuf[DD_EXTSIZE+1];
  231.  
  232.     pipename[18] = ddnam & 0x00ff;
  233.     pipename[17] = (ddnam & 0xff00) >> 8;
  234.  
  235.     fd = (int)(Fopen(pipename, 2));
  236.     if (fd < 0) return fd;
  237.  
  238.     outbuf[0] = DD_OK;
  239.     strncpy(outbuf+1, preferext, DD_EXTSIZE);
  240.  
  241.     oldpipesig = Psignal(SIGPIPE, SIG_IGN);
  242.  
  243.     if (Fwrite(fd, (long)DD_EXTSIZE+1, outbuf) != DD_EXTSIZE+1) {
  244.         ddclose(fd);
  245.         return -1;
  246.     }
  247.  
  248.     return fd;
  249. }
  250.  
  251. /*
  252.  *    ddrtry: Get the next header from the drag-and-drop originator
  253.  *
  254.  *    Input Parameters:
  255.  *    fd:        the pipe handle returned from ddopen()
  256.  *
  257.  *    Output Parameters:
  258.  *    name:        a pointer to the name of the drag & drop item
  259.  *                (note: this area must be at least DD_NAMEMAX bytes long)
  260.  *    whichext:    a pointer to the 4 byte extension
  261.  *    size:        a pointer to the size of the data
  262.  *
  263.  *    Returns:
  264.  *    0 on success
  265.  *    -1 if the originator aborts the transfer
  266.  *
  267.  *    Note: it is the caller's responsibility to actually send the
  268.  *    DD_OK byte to start the transfer, or to    send a DD_NAK, DD_EXT, or
  269.  *    DD_LEN reply with ddreply().
  270.  */
  271.  
  272. GLOBAL int ddrtry(int fd, char *name, char *whichext, long *size)
  273. {
  274.     Word hdrlen;
  275.     int i;
  276.     char buf[80];
  277.  
  278.     i = (int)(Fread(fd, 2L, &hdrlen));
  279.     if (i != 2) {
  280.         return -1;
  281.     }
  282.     if (hdrlen < 9) {    /* This should never happen */
  283.         return -1;
  284.     }
  285.     i = (int)(Fread(fd, 4L, whichext));
  286.     if (i != 4) {
  287.         return -1;
  288.     }
  289.     whichext[4] = 0;
  290.     i = (int)(Fread(fd, 4L, size));
  291.     if (i != 4) {
  292.         return -1;
  293.     }
  294.     hdrlen -= 8;
  295.     if (hdrlen > DD_NAMEMAX)
  296.         i = DD_NAMEMAX;
  297.     else
  298.         i = hdrlen;
  299.     if (Fread(fd, (long)i, name) != i) {
  300.         return -1;
  301.     }
  302.     hdrlen -= i;
  303.  
  304. /* Skip any extra header */
  305.     while (hdrlen > 80) {
  306.         Fread(fd, 80L, buf);
  307.         hdrlen -= 80;
  308.     }
  309.     if (hdrlen > 0)
  310.         Fread(fd, (long)hdrlen, buf);
  311.  
  312.     return 0;
  313. }
  314.  
  315. /*
  316.  *    send a 1 byte reply to the drag & drop originator
  317.  *
  318.  *    Input Parameters:
  319.  *    fd:        file handle returned from ddopen()
  320.  *    ack:    byte to send (e.g. DD_OK)
  321.  *
  322.  *    Output Parameters: none
  323.  *
  324.  *    Returns: 0 on success, -1 on failure
  325.  *    in the latter case the file descriptor is closed
  326.  */
  327.  
  328. GLOBAL int ddreply(int fd, int ack)
  329. {
  330.     char c = ack;
  331.  
  332.     if (Fwrite(fd, 1L, &c) != 1L) {
  333.         Fclose(fd);
  334.     }
  335.     return 0;
  336. }